/*
 * SvrInfo.cpp
 *
 *  Created on: Apr 3, 2013
 *      Author: root
 */

#include "SvrInfo.h"
#include "version.h"

/**
 * SvrInfo class init
 */
SvrInfo::SvrInfo()
{
	CpuUseTick = 0;
	start_time = time(NULL);

	memset(infodata,'\0',sizeof(infodata));
	memset(netcorver,'\0',sizeof(netcorver));

	connnum = 0;
	connfree = 0;
	connpoolsize = 0;

	iofreebufnum = 0;
	iobuftotalnum = 0;

	conntokennum = 0;
	tokentotalnum = 0;

	sessionnum = 0;
	freesessionnum = 0;

	totalBlocks = 0;
	totalSize = 0;
	freeDisk = 0;

	mem_free = 0;
    mem_total = 0;

    memset(nstat_name,'\0',sizeof(nstat_name));
	nstat_recvbytes = 0;
	nstat_recvpackets = 0;
	nstat_transbytes = 0;
	nstat_transpackets = 0;
}

/**
 * SvrInfo class free
 */
SvrInfo::~SvrInfo()
{

	/**
	 * add your code here
	 */
}


/**
 * SvrInfo init memory
 */
void SvrInfo::init(SvrConfig * pconfig,const char *corver)
{
	pSvrconfig = pconfig;
	strcpy(netcorver,corver);
}

/*
 * refresh svr info
 *
 */
void SvrInfo::refresh(long useconds,
		int connum,int confree,int conpoolsize,
		int iofreenum,int iototal,
		int tokennum,int tokentotal,
		int snum,int sfree)
{
	/*svr info*/
	this->connnum = connum;
	this->connfree = confree;
	this->connpoolsize = conpoolsize;
	this->iofreebufnum = iofreenum;
	this->iobuftotalnum = iototal;
	this->conntokennum = tokennum;
	this->tokentotalnum = tokentotal;
	this->sessionnum = snum;
	this->freesessionnum = sfree;

	/*sys info*/
	if(this->CpuUseTick == 0)
	{
		this->get_cpuoccupy((CPU_OCCUPY *)&cpu_stat1);
	}
	else if(this->CpuUseTick * useconds >= 1000000)
	{
		this->get_cpuoccupy((CPU_OCCUPY *)&cpu_stat2);
		this->cpu_use= this->cal_cpuoccupy ((CPU_OCCUPY *)&cpu_stat1, (CPU_OCCUPY *)&cpu_stat2);

		/*disk info*/
		struct statfs diskInfo;
		statfs(this->pSvrconfig->rootpath,&diskInfo);
		totalBlocks = diskInfo.f_bsize;
		totalSize = totalBlocks * diskInfo.f_blocks;
		freeDisk = diskInfo.f_bfree*totalBlocks;

		/*memory info,kB*/
		MEM_OCCUPY mem_stat;
		this->get_memoccupy(&mem_stat);
		mem_free = mem_stat.free;
		mem_total = mem_stat.total;

		/*net io stat*/
		NetIOStat nstat;
		this->get_netoccupy(&nstat);
		memset(nstat_name,'\0',sizeof(nstat_name));
		strcpy(nstat_name, nstat.name);
		this->nstat_recvbytes    =   nstat.recvbytes;
		this->nstat_recvpackets  =   nstat.recvpackets;
		this->nstat_transbytes   =   nstat.transbytes;
		this->nstat_transpackets =   nstat.transpackets;

		/*tick clear to zero*/
		this->CpuUseTick = 0;
	}

	/**
	 * tick pc
	 */
	this->CpuUseTick  ++;
}


/**
 *read SvrInfo
 */
const char *  SvrInfo::readSvrInfo()
{
	/*format time*/
	struct   tm   *start_tm;
	start_tm = localtime(&this->start_time);
	time_t curtime = time(NULL);
	long has_run_seconds = curtime - start_time;

	/*
	 * struct info list
	 * */
	memset(infodata,'\0',sizeof(infodata));
	sprintf(infodata,"%s %s<br/>core:%s<br/>start time:%04d-%02d-%02d %02d:%02d:%02d<br/>run time(s):%ld"
			"<br/>connection pool:%d/%d/%d "
			"<br/> mempool:%d/%d"
			"<br/>UserToken pool:%d/%d"
			"<br/>Task pool:%d/%d<br/>"
			"CPU use:%d<br/>"
			"Sys Memory:%lu/%lu<br/>"
			"Disk Info:%llu/%llu<br/>"
			"Net IO:%llu / %llu<br/>",
		STRSVRNAME,
		STRSVRVER,
		netcorver,
		start_tm->tm_year + 1900, start_tm->tm_mon + 1, start_tm->tm_mday , start_tm->tm_hour, start_tm->tm_min, start_tm->tm_sec,
		has_run_seconds,
		this->connnum,
		this->connfree,
		this->connpoolsize,
		this->iofreebufnum,
		this->iobuftotalnum,
		this->conntokennum,
		this->tokentotalnum,
		this->sessionnum,
		this->freesessionnum,
		this->cpu_use,
		this->mem_free,
		this->mem_total,
		this->freeDisk,
		this->totalSize,
		this->nstat_recvbytes,
		this->nstat_transbytes);

	/*return data length*/
	return this->infodata;
}


/**
 * get memory info
 */
void SvrInfo::get_memoccupy (MEM_OCCUPY *mem)
 {
     FILE *fd;
     char buff[256];
     MEM_OCCUPY *m;
     m=mem;

     fd = fopen ("/proc/meminfo", "r");

     if(fd != NULL)
     {
		 fgets (buff, sizeof(buff), fd);
		 sscanf (buff, "%s %lu", m->name, &m->total);

		 fgets (buff, sizeof(buff), fd);
		 sscanf (buff, "%s %lu", m->name2, &m->free);

		 fgets (buff, sizeof(buff), fd);
		 sscanf (buff, "%s %lu", m->name3, &m->buffers);

		 fgets (buff, sizeof(buff), fd);
		 sscanf (buff, "%s %lu", m->name4, &m->cached);

		 fgets (buff, sizeof(buff), fd);
		 sscanf (buff, "%s %lu", m->name5, &m->swapcached);

		 fclose(fd);  //close file
     }
 }

/**
 * cal_cpuoccupy
 */
int SvrInfo::cal_cpuoccupy (CPU_OCCUPY *o, CPU_OCCUPY *n)
 {
     unsigned long od, nd;
     unsigned long id, sd;
     int cpu_use = 0;

     od = (unsigned long) (o->user + o->nice + o->system +o->idle);
     nd = (unsigned long) (n->user + n->nice + n->system +n->idle);

     id = (unsigned long) (n->user - o->user);
     sd = (unsigned long) (n->system - o->system);
     if((nd-od) != 0)
    	 cpu_use = (int)((sd+id)*10000)/(nd-od);
     else
    	 cpu_use = 0;

     return cpu_use;
}

/**
 *get cpu info
 */
void SvrInfo::get_cpuoccupy (CPU_OCCUPY *cpust)
{
     FILE *fd;
     char buff[256];
     CPU_OCCUPY *cpu_occupy;
     cpu_occupy=cpust;

     fd = fopen ("/proc/stat", "r");
     if(fd != NULL)
     {
		 fgets (buff, sizeof(buff), fd);
		 sscanf (buff, "%s %u %u %u %u %u %u %u", cpu_occupy->name, &cpu_occupy->user, &cpu_occupy->nice,&cpu_occupy->system, &cpu_occupy->idle, &cpu_occupy->iowait,&cpu_occupy->irq,&cpu_occupy->softirq);

		 fclose(fd);
     }
 }

/*
 * get net io info
 */
void SvrInfo::get_netoccupy(NetIOStat * nstat)
{
	 FILE *fd;
	 char buff[256];
	 fd = fopen ("/proc/net/dev", "r");

	 if(fd == NULL)
		 return;

	 fgets (buff, sizeof(buff), fd);
	 fgets (buff, sizeof(buff), fd);

	 for(int i=0 ;i< 4; i++)
	 {
		 char * ptr = fgets (buff, sizeof(buff), fd);
		 if(ptr != NULL)
		 {
			 sscanf (buff, "%s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
						 nstat->name,
						 &nstat->recvbytes,
						 &nstat->recvpackets,
						 &nstat->recverrs,
						 &nstat->recvdrop,
						 &nstat->recvfifo,
						 &nstat->recvframe,
						 &nstat->recvcompressed,
						 &nstat->recvmulticast,
						 &nstat->transbytes,
						 &nstat->transpackets,
						 &nstat->transerrs,
						 &nstat->transdrop,
						 &nstat->transfifo,
						 &nstat->transcolls,
						 &nstat->transcarrier,
						 &nstat->transcompressed);

			 /*
			  * get specif eth
			  */
			 if(memcmp(nstat->name,this->pSvrconfig->listenethname,strlen(nstat->name)) == 0)
			 {
				 break;
			 }

			 if(memcmp(nstat->name,"lo",2) != 0 && strlen(pSvrconfig->listenethname) == 0)
			 {
				 break;
			 }
		 }
		 else
		 {
			 break;
		 }
	 }

	 fclose(fd);
}
